/** \file    boundmap.h
  * \brief   map, internally organized as bitmap, that may answer on the question: "is there any bound between pair of adjacent pixels"
  * \date    2001
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/imglib/boundmap.h,v 1.2 2006/01/16 15:46:13 cscom1r4 Exp $
  */

#ifndef _boundmap_h_
#define _boundmap_h_

#include "bitmap.h"

namespace img {

class boundmap: public bitmap
{
public:
	boundmap() {}
	//w&h in ctors is dimension of image, for which boundmap is constructed
	boundmap(size_type w, size_type h, size_type a = 0) 
		: bitmap(w+1,2*h+1,a) {}
	boundmap(size_extent e, size_type a = 0) 
		: bitmap(e.sx+1,2*e.sy+1,a) {}
	boundmap(void * data, size_type w, size_type h, size_type a = 0)
		: bitmap(data,w+1,2*h+1,a) {}
	boundmap(void * data, size_extent e, size_type a = 0) 
		: bitmap(data,e.sx+1,2*e.sy+1,a) {}

	void resize(size_type w, size_type h, size_type a = 4)
		{ bitmap::resize(w+1,2*h+1,a); }
	void resize(size_extent e, size_type a = 4) 
		{ bitmap::resize(e.sx+1,2*e.sy+1,a); }

	//boundary line segment between adjacent points (x1,y1)&(x2,y2) in coordinate system of pixels' bounds
	bit cut( int x1, int y1, int x2, int y2 );
	const_bit cut( int x1, int y1, int x2, int y2 ) const;
	bit vert_cut( int x, int y1, int y2 );
	const_bit vert_cut( int x, int y1, int y2 ) const;
	bit horiz_cut( int y, int x1, int x2 );
	const_bit horiz_cut( int y, int x1, int x2 ) const;
	//the quickest access (assume x2=x1+1, y2=y1+1)
	bit vert_cut( int x, int y1 )
		{ return at(x,2*y1+1); }
	const_bit vert_cut( int x, int y1 ) const
		{ return at(x,2*y1+1); }
	bit horiz_cut( int y, int x1 )
		{ return at(x1,2*y); }
	const_bit horiz_cut( int y, int x1 ) const
		{ return at(x1,2*y); }
	//at least one cut ends at point (x,y)
	bool any_cut( int x, int y ) const;

	//answer on the question: "is there any bound between pair of adjacent pixels" (x1,y1)&(x2,y2) in coordinate system of pixels' centres
	bit dividual( int x1, int y1, int x2, int y2 );
	const_bit dividual( int x1, int y1, int x2, int y2 ) const;
	bit vert_dividual( int x, int y1, int y2 ); ///< are pixels on the same vertical are divided
	const_bit vert_dividual( int x, int y1, int y2 ) const;
	bit horiz_dividual( int y, int x1, int x2 ); ///< are pixels on the same horizontal are divided
	const_bit horiz_dividual( int y, int x1, int x2 ) const;
	//the quickest access (assume x2=x1+1, y2=y1+1)
	bit vert_dividual( int x, int y1 )
		{ return at(x,2*y1+2); }
	const_bit vert_dividual( int x, int y1 ) const
		{ return at(x,2*y1+2); }
	bit horiz_dividual( int y, int x1 )
		{ return at(x1+1,2*y+1); }
	const_bit horiz_dividual( int y, int x1 ) const
		{ return at(x1+1,2*y+1); }
};

/////////////
// inlines //
/////////////

inline boundmap::bit boundmap::cut( int x1, int y1, int x2, int y2 ) {
	if( x1==x2 ) {
		return vert_cut( x1, y1, y2 );
	} else {
		assert(y1==y2);
		return horiz_cut( y1, x1, x2 );
	}
}

inline boundmap::const_bit boundmap::cut( int x1, int y1, int x2, int y2 ) const {
	if( x1==x2 ) {
		return vert_cut( x1, y1, y2 );
	} else {
		assert(y1==y2);
		return horiz_cut( y1, x1, x2 );
	}
}

inline boundmap::bit boundmap::vert_cut( int x, int y1, int y2 ) {
	if( y2 == y1+1 ) {
		return vert_cut( x, y1 );
	} else {
		assert( y1 == y2+1 );
		return vert_cut( x, y2 );
	}
}

inline boundmap::const_bit boundmap::vert_cut( int x, int y1, int y2 ) const {
	if( y2 == y1+1 ) {
		return vert_cut( x, y1 );
	} else {
		assert( y1 == y2+1 );
		return vert_cut( x, y2 );
	}
}

inline boundmap::bit boundmap::horiz_cut( int y, int x1, int x2 ) {
	if( x2 == x1+1 ) {
		return horiz_cut( y, x1 );
	} else {
		assert( x1 == x2+1 );
		return horiz_cut( y, x2 );
	}
}

inline boundmap::const_bit boundmap::horiz_cut( int y, int x1, int x2 ) const {
	if( x2 == x1+1 ) {
		return horiz_cut( y, x1 );
	} else {
		assert( x1 == x2+1 );
		return horiz_cut( y, x2 );
	}
}

inline bool boundmap::any_cut( int x, int y ) const {
	return vert_cut(x,y-1) || vert_cut(x,y) || horiz_cut(y,x-1) || horiz_cut(y,x);
}

inline boundmap::bit boundmap::dividual( int x1, int y1, int x2, int y2 ) {
	if( x1==x2 ) {
		return vert_dividual( x1, y1, y2 );
	} else {
		assert(y1==y2);
		return horiz_dividual( y1, x1, x2 );
	}
}

inline boundmap::const_bit boundmap::dividual( int x1, int y1, int x2, int y2 ) const {
	if( x1==x2 ) {
		return vert_dividual( x1, y1, y2 );
	} else {
		assert(y1==y2);
		return horiz_dividual( y1, x1, x2 );
	}
}

inline boundmap::bit boundmap::vert_dividual( int x, int y1, int y2 ) {
	if( y2 == y1+1 ) {
		return vert_dividual( x, y1 );
	} else {
		assert( y1 == y2+1 );
		return vert_dividual( x, y2 );
	}
}

inline boundmap::const_bit boundmap::vert_dividual( int x, int y1, int y2 ) const {
	if( y2 == y1+1 ) {
		return vert_dividual( x, y1 );
	} else {
		assert( y1 == y2+1 );
		return vert_dividual( x, y2 );
	}
}

inline boundmap::bit boundmap::horiz_dividual( int y, int x1, int x2 ) {
	if( x2 == x1+1 ) {
		return horiz_dividual( y, x1 );
	} else {
		assert( x1 == x2+1 );
		return horiz_dividual( y, x2 );
	}
}

inline boundmap::const_bit boundmap::horiz_dividual( int y, int x1, int x2 ) const {
	if( x2 == x1+1 ) {
		return horiz_dividual( y, x1 );
	} else {
		assert( x1 == x2+1 );
		return horiz_dividual( y, x2 );
	}
}

} //namespace img

#endif //_boundmap_h_
